home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 8: LINUX Games
/
Linux Cubed Series 8 - LINUX Games.iso
/
games
/
muds
/
mordor_2.000
/
mordor_2
/
src
/
update.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-06-25
|
24KB
|
816 lines
/*
* UPDATE.C:
*
* Routines to handle non-player game updates.
*
* Copyright (C) 1991, 1992, 1993 Brett J. Vickers
*
*/
#include "mstruct.h"
#include "mextern.h"
#include "update.h"
static long last_update;
static long last_user_update;
static long last_random_update;
static long last_active_update;
static long last_time_update;
static long last_shutdown_update;
static long last_allcmd;
long last_exit_update;
long TX_interval = 4200;
short Random_update_interval = 20;
static ctag *first_active;
extern void update_allcmd();
/**********************************************************************/
/* update_game */
/**********************************************************************/
/* This function handles all the updates that occur while players are */
/* typing. */
void update_game()
{
long t;
t = time(0);
if(t == last_update)
return;
last_update = t;
if(t - last_user_update >= 20)
update_users(t);
if(t - last_random_update >= Random_update_interval)
update_random(t);
if(t != last_active_update)
update_active(t);
if(t - last_time_update >= 150)
update_time(t);
if(t - last_exit_update >= TX_interval)
update_exit(t);
if(Shutdown.ltime && t - last_shutdown_update >= 30)
if(Shutdown.ltime + Shutdown.interval <= t+500)
update_shutdown(t);
#ifdef RECORD_ALL
if(t- last_allcmd >= 300)
update_allcmd(t);
#endif RECORD_ALL
}
/**********************************************************************/
/* update_users */
/**********************************************************************/
/* This function controls user updates. Every 20 seconds it checks a */
/* user's time-out flags (such as invisibility, etc.) and it also */
/* checks for excessive idle times. If a user has been idle for over */
/* 30 mins, he is disconnected. */
void update_users(t)
long t;
{
int i;
last_user_update = t;
for(i=0; i<Tablesize; i++) {
if(!Ply[i].io) continue;
if(Ply[i].ply && Ply[i].ply->class == DM) continue;
if(t - Ply[i].io->ltime > 300 && Ply[i].io->fn != waiting) {
write(i, "\n\rTimed out.\n\r", 14);
disconnect(i);
continue;
}
if(!Ply[i].ply) continue;
if(Ply[i].ply->fd < 0) continue;
update_ply(Ply[i].ply);
}
}
/**********************************************************************/
/* update_random */
/**********************************************************************/
/* This function checks all player-occupied rooms to see if random monsters */
/* have entered them. If it is determined that random monster should enter */
/* a room, it is loaded and items it is carrying will be loaded with it. */
void update_random(t)
long t;
{
creature *crt_ptr;
object *obj_ptr;
room *rom_ptr;
int check[PMAX];
int num, m, n, i, j, k, l, total = 0;
last_random_update = t;
for(i=0; i<Tablesize; i++) {
if(!Ply[i].ply || !Ply[i].io) continue;
if(Ply[i].ply->fd < 0) continue;
rom_ptr = Ply[i].ply->parent_rom;
for(j=0; j<total; j++)
if(check[j] == rom_ptr->rom_num) break;
if(j < total) continue;
check[total++] = rom_ptr->rom_num;
if(mrand(1,100) > rom_ptr->traffic) continue;
n = mrand(0,9);
if(!rom_ptr->random[n]) continue;
m = load_crt(rom_ptr->random[n], &crt_ptr);
if(m < 0) continue;
if(F_ISSET(rom_ptr, RPLWAN))
num = mrand(1, count_ply(rom_ptr));
else if(crt_ptr->numwander > 1)
num = mrand(1, crt_ptr->numwander);
else
num = 1;
for(l=0; l<num; l++) {
crt_ptr->lasttime[LT_ATTCK].ltime =
crt_ptr->lasttime[LT_MSCAV].ltime =
crt_ptr->lasttime[LT_MWAND].ltime = t;
if(crt_ptr->dexterity < 20)
crt_ptr->lasttime[LT_ATTCK].interval = 3;
else
crt_ptr->lasttime[LT_ATTCK].interval = 2;
j = mrand(1,100);
if(j<90) j=1;
else if(j<96) j=2;
else j=3;
for(k=0; k<j; k++) {
m = mrand(0,9);
if(crt_ptr->carry[m]) {
m=load_obj(crt_ptr->carry[m],
&obj_ptr);
if(m > -1) {
if(F_ISSET(obj_ptr, ORENCH))
rand_enchant(obj_ptr);
obj_ptr->value =
mrand((obj_ptr->value*9)/10,
(obj_ptr->value*11)/10);
add_obj_crt(obj_ptr, crt_ptr);
}
}
}
if(!F_ISSET(crt_ptr, MNRGLD) && crt_ptr->gold)
crt_ptr->gold =
mrand(crt_ptr->gold/10, crt_ptr->gold);
if(!l)
add_crt_rom(crt_ptr, rom_ptr, num);
else
add_crt_rom(crt_ptr, rom_ptr, 0);
add_active(crt_ptr);
if(l != num-1)
load_crt(rom_ptr->random[n], &crt_ptr);
}
}
}
/************************************************************************/
/* update_active */
/************************************************************************/
/* This function updates the activities of all monsters who are currently */
/* active (ie. monsters on the active list). Usually this is reserved */
/* for monsters in rooms that are occupied by players. */
void update_active(t)
long t;
{
creature *crt_ptr, *att_ptr;
object *obj_ptr;
room *rom_ptr;
ctag *cp;
char *enemy;
long i,z;
int rtn = 0, n, fd, p=0;
last_active_update = t;
if(!(cp = first_active)) return;
while(cp) {
if(!cp) break;
crt_ptr = cp->crt;
rom_ptr = crt_ptr->parent_rom;
if(!rom_ptr->first_ply) {
del_active(crt_ptr);
cp = first_active;
continue;
}
i = LT(crt_ptr, LT_ATTCK);
if(i > t) {
cp = cp->next_tag;
continue;
}
i = LT(crt_ptr, LT_HEALS);
while(i <= t && (crt_ptr->hpcur < crt_ptr->hpmax ||
crt_ptr->mpcur < crt_ptr->mpmax)) {
crt_ptr->hpcur += MAX(1,crt_ptr->hpmax/10);
if(crt_ptr->hpcur > crt_ptr->hpmax)
crt_ptr->hpcur = crt_ptr->hpmax;
crt_ptr->mpcur += MAX(1,crt_ptr->mpmax/6);
if(crt_ptr->mpcur > crt_ptr->mpmax)
crt_ptr->mpcur = crt_ptr->mpmax;
i += 60L;
crt_ptr->lasttime[LT_HEALS].ltime = t;
crt_ptr->lasttime[LT_HEALS].interval = 60L;
}
if (t > LT(crt_ptr, LT_CHRMD)&&F_ISSET(crt_ptr, MCHARM))
F_CLR(crt_ptr, MCHARM);
crt_ptr->lasttime[LT_ATTCK].ltime = t;
if(crt_ptr->dexterity < 20)
crt_ptr->lasttime[LT_ATTCK].interval = 3;
else
crt_ptr->lasttime[LT_ATTCK].interval = 2;
if(F_ISSET(crt_ptr, MSCAVE)) {
i = crt_ptr->lasttime[LT_MSCAV].ltime;
if(t-i > 20 && mrand(1,100) <= 15 &&
rom_ptr->first_obj &&
!F_ISSET(rom_ptr->first_obj->obj, ONOTAK) &&
!F_ISSET(rom_ptr->first_obj->obj, OSCENE) &&
!F_ISSET(rom_ptr->first_obj->obj, OHIDDN) &&
!F_ISSET(rom_ptr->first_obj->obj, OPERM2) &&
!F_ISSET(rom_ptr->first_obj->obj, OPERMT)) {
obj_ptr = rom_ptr->first_obj->obj;
del_obj_rom(obj_ptr, rom_ptr);
add_obj_crt(obj_ptr, crt_ptr);
F_SET(crt_ptr, MHASSC);
broadcast_rom(-1, crt_ptr->rom_num,
"%M picked up %1i.",
crt_ptr, obj_ptr);
}
if(t-i > 20)
crt_ptr->lasttime[LT_MSCAV].ltime = t;
}
if(!F_ISSET(crt_ptr, MHASSC) && !F_ISSET(crt_ptr, MPERMT) && !F_ISSET(crt_ptr, MDMFOL)) {
i = crt_ptr->lasttime[LT_MWAND].ltime;
if(t-i > 20
&& mrand(1,100) <= crt_ptr->parent_rom->traffic
&& !crt_ptr->first_enm) {
broadcast_rom(-1, crt_ptr->rom_num,
"%1M just wandered away.",
crt_ptr);
del_crt_rom(crt_ptr, rom_ptr);
del_active(crt_ptr);
free_crt(crt_ptr);
cp = first_active;
continue;
}
if(t-i > 20)
crt_ptr->lasttime[LT_MWAND].ltime = t;
}
if(!crt_ptr->first_enm && (!F_ISSET(crt_ptr, MAGGRE) &&
!F_ISSET(crt_ptr, MGAGGR) && !F_ISSET(crt_ptr, MEAGGR))) {
cp = cp->next_tag;
continue;
}
if(crt_ptr->first_enm) {
enemy = crt_ptr->first_enm->enemy;
att_ptr = find_crt(crt_ptr, rom_ptr->first_ply,
enemy, 1);
if(!att_ptr) {
if(!find_who(enemy))
del_enm_crt(enemy, crt_ptr);
else
end_enm_crt(enemy, crt_ptr);
}
else {
if(is_charm_crt(crt_ptr->name, att_ptr)&& F_ISSET(crt_ptr, MCHARM))
p = 1;
crt_ptr->NUMHITS++;
n=20;
if(F_ISSET(crt_ptr, MMAGIO))
n=crt_ptr->proficiency[0];
if(F_ISSET(crt_ptr, MMAGIC) && mrand(1, 100) <= n && !p) {
rtn = crt_spell(crt_ptr, att_ptr);
if(!rom_ptr->first_ply) {
del_active(crt_ptr);
cp = first_active;
continue;
}
if(rtn == 2) {
cp = first_active;
continue;
}
else if(rtn == 1)
n = 21;
else n = crt_ptr->thaco - att_ptr->armor/10;
}
else {
n = crt_ptr->thaco - att_ptr->armor/10;
n = MAX(n, 1);
}
if(mrand(1,20) >= n && !p) {
fd = att_ptr->fd;
ANSI(fd, RED);
if(F_ISSET(crt_ptr, MBRETH) && mrand(1,30)<5)
if (F_ISSET(crt_ptr, MBRWP1) && !F_ISSET(crt_ptr, MBRWP2))
{
print(fd, "%M spits acid on you!\n", crt_ptr);
broadcast_rom(fd, att_ptr->rom_num,
"%M spits acid on %M!", crt_ptr, att_ptr);
n = dice(crt_ptr->level, 3, 0);
}
else if (F_ISSET(crt_ptr, MBRWP1) && F_ISSET(crt_ptr, MBRWP2))
{
print(fd, "%M breathe poisonous gas on you!\n", crt_ptr);
broadcast_rom(fd, att_ptr->rom_num,
"%M breathes poisonous gas on %M!", crt_ptr, att_ptr);
n = dice(crt_ptr->level, 2, 1);
print(fd, "%M poisoned you.\n", crt_ptr);
F_SET(att_ptr, PPOISN);
}
else if (!F_ISSET(crt_ptr, MBRWP1) && F_ISSET(crt_ptr, MBRWP2))
{
print(fd, "%M breathe frost on you!\n", crt_ptr);
broadcast_rom(fd, att_ptr->rom_num,
"%M breathes frost on %M!", crt_ptr, att_ptr);
if(F_ISSET(att_ptr, PRCOLD))
n = dice(crt_ptr->level, 2, 0);
else
n = dice(crt_ptr->level, 4, 0);
}
else{
print(fd, "%M breathe fire on you!\n", crt_ptr);
broadcast_rom(fd, att_ptr->rom_num,
"%M breathes fire on %M!", crt_ptr, att_ptr);
if(F_ISSET(att_ptr, PRFIRE))
n = dice(crt_ptr->level, 2, 0);
else
n = dice(crt_ptr->level, 4, 0);
}
else
{
if(F_ISSET(crt_ptr, MENEDR) && mrand(1,100)< 10)
{
n = dice(crt_ptr->level, 5, (crt_ptr->level)*5);
n = MAX(0,MIN(n,att_ptr->experience));
print(fd, "%M drains your experience!\n", crt_ptr);
broadcast_rom(fd, att_ptr->rom_num,
"%M energy drains %M!", crt_ptr, att_ptr);
att_ptr->experience -= n;
lower_prof(att_ptr,n);
print(fd, "%M drains you for %d experience.\n",crt_ptr,n);
}
n = mdice(crt_ptr);
}
att_ptr->hpcur -= n;
print(fd, "%M hit you for %d damage.\n",
crt_ptr, n);
if(F_ISSET(crt_ptr, MPOISS) &&
mrand(1,100) <= 15) {
print(fd, "%M poisoned you.\n",
crt_ptr);
F_SET(att_ptr, PPOISN);
}
if(F_ISSET(crt_ptr, MDISEA) &&
mrand(1,100) <= 15) {
print(fd, "%M infects you.\n",
crt_ptr);
F_SET(att_ptr, PDISEA);
}
if(F_ISSET(crt_ptr, MBLNDR) &&
mrand(1,100) <= 15) {
print(fd, "%M blinds your eyes.\n",
crt_ptr);
F_SET(att_ptr, PBLIND);
}
if(F_ISSET(crt_ptr, MDISIT) &&
mrand(1,100) <= 15)
dissolve_item(att_ptr,crt_ptr);
ANSI(fd, WHITE);
n = choose_item(att_ptr);
if(n) {
if(--att_ptr->ready[n-1]->shotscur<1) {
print(fd,
"Your %s fell apart.\n",
att_ptr->ready[n-1]->name);
broadcast_rom(fd,
att_ptr->rom_num,
"%M's %s fell apart.",
att_ptr,
att_ptr->ready[n-1]->name);
add_obj_crt(att_ptr->ready[n-1],
att_ptr);
att_ptr->ready[n-1] = 0;
compute_ac(att_ptr);
}
}
if(t - Ply[att_ptr->fd].io->ltime > 5L &&
crt_ptr->NUMHITS > 1 && !F_ISSET(att_ptr,PNOAAT) && !p) {
rtn = attack_crt(att_ptr, crt_ptr);
if(rtn) {
cp = first_active;
continue;
}
}
if(att_ptr->hpcur < 1) {
ANSI(fd, MAGENTA);
print(fd, "%M killed you.\n", crt_ptr);
ANSI(fd, WHITE);
die(att_ptr, crt_ptr);
cp = first_active;
continue;
}
else if(F_ISSET(att_ptr, PWIMPY)) {
if(att_ptr->hpcur <= att_ptr->WIMPYVALUE) {
flee(att_ptr);
cp = first_active;
continue;
}
}
else if(F_ISSET(att_ptr, PFEARS)) {
int ff;
ff = 40 + (1- (att_ptr->hpcur/att_ptr->hpmax))*40 +
bonus[att_ptr->constitution]*3 +
(att_ptr->class == PALADIN) ? -10 : 0;
if(ff < mrand(1,100)) {
flee(att_ptr);
cp = first_active;
continue;
}
}
}
else if(n <= 20 && !p) {
ANSI(att_ptr->fd, CYAN);
print(att_ptr->fd, "%M missed you.\n", crt_ptr);
ANSI(att_ptr->fd, WHITE);
if(t - Ply[att_ptr->fd].io->ltime > 5L &&
crt_ptr->NUMHITS > 1) {
rtn = attack_crt(att_ptr, crt_ptr);
if(rtn) {
cp = first_active;
continue;
}
}
}
cp = cp->next_tag;
continue;
}
}
if(F_ISSET(crt_ptr, MAGGRE) || F_ISSET(crt_ptr, MGAGGR) ||
F_ISSET(crt_ptr, MEAGGR)) {
if (F_ISSET(crt_ptr, MAGGRE))
att_ptr = lowest_piety(rom_ptr, F_ISSET(crt_ptr, MDINVI) ? 1:0);
else {
att_ptr = low_piety_alg(rom_ptr,
F_ISSET(crt_ptr, MDINVI) ? 1:0,
F_ISSET(crt_ptr,MGAGGR) ? -1 : 1,crt_ptr->level);
}
if(!att_ptr) {
cp = cp->next_tag;
continue;
}
ANSI(att_ptr->fd, RED);
print(att_ptr->fd, "%M attacks you.\n", crt_ptr);
ANSI(att_ptr->fd, WHITE);
crt_ptr->lasttime[LT_ATTCK].interval = 0;
broadcast_rom(att_ptr->fd, att_ptr->rom_num,
"%M attacks %m.",
crt_ptr, att_ptr);
add_enm_crt(att_ptr->name, crt_ptr);
}
cp = cp->next_tag;
}
}
/************************************************************************/
/* choose_item */
/************************************************************************/
/* This function randomly chooses an item that the player pointed to */
/* by the first argument is wearing. */
int choose_item(ply_ptr)
creature *ply_ptr;
{
char checklist[MAXWEAR];
int numwear=0, i;
for(i=0; i<MAXWEAR; i++) {
checklist[i] = 0;
if(i==WIELD-1 || i==HELD-1) continue;
if(ply_ptr->ready[i])
checklist[numwear++] = i+1;
}
if(!numwear) return(0);
i = mrand(0, numwear-1);
return(checklist[i]);
}
/**********************************************************************/
/* crt_spell */
/**********************************************************************/
/* This function allows monsters to cast spells at players. */
int crt_spell(crt_ptr, att_ptr)
creature *crt_ptr;
creature *att_ptr;
{
cmd cmnd;
int i, j, spl, c;
int known[10], knowctr = 0;
int (*fn)();
for(i=0; i<16; i++) {
if(!crt_ptr->spells[i]) continue;
for(j=i*8; j<=(i*8+7); j++) {
if(knowctr > 9) break;
if(S_ISSET(crt_ptr, j))
known[knowctr++] = j;
}
if(knowctr > 9) break;
}
if(!knowctr)
spl = 1;
else {
i = mrand(1, knowctr);
spl = known[i-1];
}
if ((spllist[spl].splno != SVIGOR) &&
(spllist[spl].splno != SMENDW) &&
(spllist[spl].splno != SFHEAL)){
strcpy(cmnd.str[2], att_ptr->name);
cmnd.val[2] = 1;
cmnd.num = 3;
} else
cmnd.num = 2;
fn = spllist[spl].splfn;
ANSI(att_ptr->fd, RED);
if(fn == offensive_spell) {
for(c=0; ospell[c].splno != spllist[spl].splno; c++)
if(ospell[c].splno == -1) return(0);
i = (*fn)(crt_ptr, &cmnd, CAST, spllist[spl].splstr,
&ospell[c]);
}
else i = (*fn)(crt_ptr, &cmnd, CAST);
ANSI(att_ptr->fd, WHITE);
return(i);
}
/**********************************************************************/
/* update_time */
/**********************************************************************/
/* This function updates the game time in hours. When it is 6am a sunrise */
/* message is broadcast. When it is 8pm a sunset message is broadcast. */
void update_time(t)
long t;
{
int daytime;
last_time_update = t;
Time++;
daytime = (int)(Time % 24L);
if(daytime == 6)
broadcast("The sun rises.");
else if(daytime == 20)
broadcast("The sun disappears over the horizon.");
}
/**********************************************************************/
/* update_shutdown */
/**********************************************************************/
/* This function broadcasts a shutdown message every 30 seconds until */
/* shutdown is achieved. Then it saves off all rooms and players, */
/* and exits the game. */
void update_shutdown(t)
long t;
{
long i;
char path[128];
last_shutdown_update = t;
i = Shutdown.ltime + Shutdown.interval;
if(i > t) {
if(i-t > 60)
broadcast("### Game shutdown in %d:%02d minutes.",
(i-t)/60L, (i-t)%60L);
else
broadcast("### Game shutdown in %d seconds.", i-t);
}
else {
broadcast("### Shutting down now.");
output_buf();
logf("--- Game shut down ---\n");
resave_all_rom(1);
save_all_ply();
#ifdef RECORD_ALL
sprintf(path,"%s/%s",LOGPATH,"all_cmd");
unlink(path);
#endif RECORD_ALL
kill(getpid(), 9);
exit(0);
}
}
/**********************************************************************/
/* add_active */
/**********************************************************************/
/* This function adds a monster to the active-monster list. A pointer */
/* to the monster is passed in the first parameter. */
void add_active(crt_ptr)
creature *crt_ptr;
{
ctag *cp, *ct;
del_active(crt_ptr);
if(!crt_ptr)
return;
ct = (ctag *)malloc(sizeof(ctag));
if(!ct)
merror("add_active", FATAL);
ct->crt = crt_ptr;
ct->next_tag = 0;
if(!first_active)
first_active = ct;
else {
ct->next_tag = first_active;
first_active = ct;
}
}
/**********************************************************************/
/* del_active */
/**********************************************************************/
/* This function removes a monster from the active-monster list. The */
/* parameter contains a pointer to the monster which is to be removed */
void del_active(crt_ptr)
creature *crt_ptr;
{
ctag *cp, *prev;
if(!(cp = first_active)) return;
if(cp->crt == crt_ptr) {
first_active = cp->next_tag;
free(cp);
return;
}
prev = cp;
cp = cp->next_tag;
while(cp) {
if(cp->crt == crt_ptr) {
prev->next_tag = cp->next_tag;
free(cp);
return;
}
prev = cp;
cp = cp->next_tag;
}
}
/*===================================================================*/
/* update_exit */
/*===================================================================*/
void update_exit(t)
long t;
{
room *rom_ptr;
xtag *xp;
char *tmp;
int i,x;
last_exit_update = t;
for(i=0;i<MAX_TEXIT; i++){
if(load_rom( time_x[i].room,&rom_ptr) < 0)
return;
xp = rom_ptr->first_ext;
while(xp){
if((time_x[i].name1) && (time_x[i].exit1 == xp->ext->room)
&& (!strcmp(xp->ext->name,time_x[i].name1)))
F_SET(xp->ext,XNOSEE);
if((time_x[i].name2) && (time_x[i].exit2 == xp->ext->room)
&& (!strcmp(xp->ext->name,time_x[i].name2)))
F_CLR(xp->ext,XNOSEE);
xp = xp->next_tag;
}
tmp = time_x[i].name1;
x = time_x[i].exit1;
time_x[i].name1 = time_x[i].name2;
time_x[i].exit1 = time_x[i].exit2;
time_x[i].name2 = tmp;
time_x[i].exit2 = x;
if (!t_toggle)
tmp = time_x[i].mess1;
else
tmp = time_x[i].mess2;
if (tmp)
broadcast("\n%s",tmp);
t_toggle = !t_toggle;
}
}
/*====================================================================*/
void update_allcmd(t)
long t;
{
char path[128];
last_allcmd = t;
sprintf(path,"%s/%s",LOGPATH,"all_cmd");
unlink(path);
}
/*************************************/
int list_act(ply_ptr, cmnd)
creature *ply_ptr;
cmd *cmnd;
{
ctag *cp;
if (ply_ptr->class < DM)
return(0);
print(ply_ptr->fd,"Active monster list\n");
cp = first_active;
while(cp){
print(ply_ptr->fd,"Name:%s.\n",cp->crt->name);
cp = cp->next_tag;
}
output_buf();
return;
}